package mapping

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"

	"pgm/internal/config"
	"pgm/internal/models"

	"gopkg.in/yaml.v2"
)

// Manager 映射配置管理器
type Manager struct {
	configFile string
	mappings   *models.MappingConfig
	mutex      sync.RWMutex
}

var instance *Manager
var once sync.Once

// GetManager 获取映射管理器单例
func GetManager() *Manager {
	once.Do(func() {
		instance = &Manager{
			configFile: config.AppConfig.Mapping.ConfigFile,
			mappings:   &models.MappingConfig{},
		}
		instance.loadConfig()
	})
	return instance
}

// loadConfig 加载映射配置
func (m *Manager) loadConfig() error {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	// 检查配置文件是否存在
	if _, err := os.Stat(m.configFile); os.IsNotExist(err) {
		// 创建默认配置
		m.mappings = &models.MappingConfig{
			Mappings: make(map[string]models.TableMapping),
			Global: models.GlobalConfig{
				Pagination: models.PaginationConfig{
					DefaultPageSize: 20,
					MaxPageSize:     100,
				},
				DateFormat: "2006-01-02 15:04:05",
				Timezone:   "Asia/Shanghai",
			},
		}
		return m.saveConfig()
	}

	// 读取配置文件
	data, err := ioutil.ReadFile(m.configFile)
	if err != nil {
		return fmt.Errorf("读取映射配置文件失败: %w", err)
	}

	// 解析YAML
	if err := yaml.Unmarshal(data, m.mappings); err != nil {
		return fmt.Errorf("解析映射配置失败: %w", err)
	}

	// 确保mappings不为nil
	if m.mappings.Mappings == nil {
		m.mappings.Mappings = make(map[string]models.TableMapping)
	}

	return nil
}

// saveConfig 保存映射配置
func (m *Manager) saveConfig() error {
	data, err := yaml.Marshal(m.mappings)
	if err != nil {
		return fmt.Errorf("序列化映射配置失败: %w", err)
	}

	// 确保目录存在
	dir := filepath.Dir(m.configFile)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("创建配置目录失败: %w", err)
	}

	// 写入文件
	if err := ioutil.WriteFile(m.configFile, data, 0644); err != nil {
		return fmt.Errorf("写入映射配置文件失败: %w", err)
	}

	return nil
}

// GetTableMapping 获取表映射配置
func (m *Manager) GetTableMapping(tableName string) (*models.TableMapping, bool) {
	m.mutex.RLock()
	defer m.mutex.RUnlock()

	mapping, exists := m.mappings.Mappings[tableName]
	return &mapping, exists
}

// SetTableMapping 设置表映射配置
func (m *Manager) SetTableMapping(tableName string, mapping models.TableMapping) error {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	m.mappings.Mappings[tableName] = mapping
	return m.saveConfig()
}

// DeleteTableMapping 删除表映射配置
func (m *Manager) DeleteTableMapping(tableName string) error {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	delete(m.mappings.Mappings, tableName)
	return m.saveConfig()
}

// GetAllMappings 获取所有映射配置
func (m *Manager) GetAllMappings() map[string]models.TableMapping {
	m.mutex.RLock()
	defer m.mutex.RUnlock()

	// 深拷贝
	result := make(map[string]models.TableMapping)
	for k, v := range m.mappings.Mappings {
		result[k] = v
	}
	return result
}

// GetGlobalConfig 获取全局配置
func (m *Manager) GetGlobalConfig() models.GlobalConfig {
	m.mutex.RLock()
	defer m.mutex.RUnlock()

	return m.mappings.Global
}

// SetGlobalConfig 设置全局配置
func (m *Manager) SetGlobalConfig(globalConfig models.GlobalConfig) error {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	m.mappings.Global = globalConfig
	return m.saveConfig()
}

// ReloadConfig 重新加载配置
func (m *Manager) ReloadConfig() error {
	return m.loadConfig()
}

// GetDisplayName 获取表的显示名称
func (m *Manager) GetDisplayName(tableName string) string {
	if mapping, exists := m.GetTableMapping(tableName); exists && mapping.DisplayName != "" {
		return mapping.DisplayName
	}
	return tableName
}

// GetFieldDisplayName 获取字段的显示名称
func (m *Manager) GetFieldDisplayName(tableName, fieldName string) string {
	if mapping, exists := m.GetTableMapping(tableName); exists {
		if fieldMapping, fieldExists := mapping.Fields[fieldName]; fieldExists && fieldMapping.DisplayName != "" {
			return fieldMapping.DisplayName
		}
	}
	return fieldName
}

// IsFieldHidden 检查字段是否隐藏
func (m *Manager) IsFieldHidden(tableName, fieldName string) bool {
	if mapping, exists := m.GetTableMapping(tableName); exists {
		if fieldMapping, fieldExists := mapping.Fields[fieldName]; fieldExists {
			return fieldMapping.Hidden
		}
	}
	return false
}

// IsFieldReadonly 检查字段是否只读
func (m *Manager) IsFieldReadonly(tableName, fieldName string) bool {
	if mapping, exists := m.GetTableMapping(tableName); exists {
		if fieldMapping, fieldExists := mapping.Fields[fieldName]; fieldExists {
			return fieldMapping.Readonly
		}
	}
	return false
}

// IsFieldRequired 检查字段是否必填
func (m *Manager) IsFieldRequired(tableName, fieldName string) bool {
	if mapping, exists := m.GetTableMapping(tableName); exists {
		if fieldMapping, fieldExists := mapping.Fields[fieldName]; fieldExists {
			return fieldMapping.Required
		}
	}
	return false
}

// GetFieldValidation 获取字段验证规则
func (m *Manager) GetFieldValidation(tableName, fieldName string) string {
	if mapping, exists := m.GetTableMapping(tableName); exists {
		if fieldMapping, fieldExists := mapping.Fields[fieldName]; fieldExists {
			return fieldMapping.Validation
		}
	}
	return ""
}

// IsOperationAllowed 检查是否允许某种操作
func (m *Manager) IsOperationAllowed(tableName string, operation string) bool {
	if mapping, exists := m.GetTableMapping(tableName); exists {
		switch operation {
		case "create":
			return mapping.Operations.Create
		case "read":
			return mapping.Operations.Read
		case "update":
			return mapping.Operations.Update
		case "delete":
			return mapping.Operations.Delete
		}
	}
	// 默认允许所有操作
	return true
}

// CreateDefaultMapping 为表创建默认映射配置
func (m *Manager) CreateDefaultMapping(tableName string, tableInfo interface{}) models.TableMapping {
	mapping := models.TableMapping{
		DisplayName: tableName,
		Description: fmt.Sprintf("表 %s 的管理界面", tableName),
		Icon:        "table",
		Fields:      make(map[string]models.FieldMapping),
		Operations: models.OperationMapping{
			Create: true,
			Read:   true,
			Update: true,
			Delete: true,
		},
		Permissions: models.PermissionMapping{
			Roles: []string{"admin"},
		},
	}

	// 这里可以根据tableInfo来设置字段映射
	// 由于tableInfo类型未明确，暂时留空

	return mapping
}
